local skynet = require "skynet"
local mysql = require "mysql"
local snax = require "snax"
local cluster = require "cluster"
local sharedata = require "sharedata"
local CMD = require "center_proto"
local MAIN = require "main_proto"
local CARDCMD = require "needCard"
local db = require "dblib"

local HALL ={}
local GameServerShareObj = nil
local centerserver = nil
--**********************大厅相关逻辑*************************

-- 客户端请求创建代理房间
function HALL.CreateAgentTableReq( msg )
    local gameid,agentid,mode,ju,difen,ma,fangpao,dianpao,qiang,playcount = string.unpack("<I4I4I4<H<I4I4I4I4I4I4", msg, 1)
    skynet.error("[HALL CreateAgentTableReq] GID="..gameid.." agid="..agentid.." mode="..mode.." ju="..ju.." difen="..difen.." ma="..ma.." fangpao="..fangpao.." dianpao="..dianpao.." qiang="..qiang.." playcount="..playcount)

    -- 进行代理人有关的检查
    local cost = CARDCMD.GetNeedCard(1, ju, playcount, gameid)
    skynet.error("cost="..cost)

    local s1, res = db.call("call  pr_AgentCheckCreateTable("..agentid..","..cost..",@ReturnVal,@szmsg)", "select @ReturnVal,@szmsg")

    local result = res[1]['@ReturnVal']
    local msg    = res[1]['@szmsg']

    skynet.error("[hallser] CreateAgentTableReq : "..agentid..","..result..","..msg)

    local re = {mcmd = CMD.Main_hall_module,scmd = CMD.Sub_CreateAgentTableResp, msg = string.pack("<i4c128",tonumber(result),msg) }
    return re

end

function readRandomValueInTable(Table)
    local tmpKeyT={}
    local n=1
    for k in pairs(Table) do
        tmpKeyT[n]=k
        n=n+1
    end
    return Table[tmpKeyT[math.random(1,n-1)]]
end

-- 客户端二次创建代理房间
function HALL.CreateAgentTableReq2( msg )

    local gameid,agentid,mode,ju,difen,ma,fangpao,dianpao,qiang,playcount = string.unpack("<I4I4I4<H<I4I4I4I4I4I4", msg, 1)
    skynet.error("[HALL CreateAgentTableReq] GID="..gameid.." agid="..agentid.." mode="..mode.." ju="..ju.." difen="..difen.." ma="..ma.." fangpao="..fangpao.." dianpao="..dianpao.." qiang="..qiang.." playcount="..playcount)

    -- 进行代理人有关的检查
    local cost = CARDCMD.GetNeedCard(1, ju, playcount, gameid)
    skynet.error("二次创建 cost="..cost)
    local s1, res = db.call("call  pr_AgentCheckCreateTable("..agentid..","..cost..",@ReturnVal,@szmsg)", "select @ReturnVal,@szmsg")

    local result = res[1]['@ReturnVal']
    local szmsg  = res[1]['@szmsg']

    skynet.error("[HALL CreateAgentTableReq2] : "..agentid..","..result..","..szmsg)

    if result<0 then 
        local re = {mcmd = CMD.Main_hall_module,scmd = CMD.Sub_CreateAgentTableResp2, msg = string.pack("<i4c128",result,szmsg) }
        return re
    end

    if GameServerShareObj[CMD.GameType_Friend] == nil then
        skynet.error("无此游戏类型 GameType_Friend")
        local re = {mcmd = CMD.Main_hall_module,scmd = CMD.Sub_CreateAgentTableResp2, msg = string.pack("<i4c128",0,'暂无此游戏房间') }
        return re
    end

    if GameServerShareObj[CMD.GameType_Friend][gameid] == nil then
        skynet.error("无此游戏房间 gameid="..gameid)
        local re = {mcmd = CMD.Main_hall_module,scmd = CMD.Sub_CreateAgentTableResp2, msg = string.pack("<i4c128",0,'暂无此游戏房间') }
        return re
    end
    
    math.randomseed(tostring(os.time()):reverse():sub(1, 6))
    
    -- 随机选择一个服务器
    local adx = readRandomValueInTable(GameServerShareObj[CMD.GameType_Friend][gameid])

    skynet.error("发送二次创建 游戏服务器地址= "..adx)
    skynet.send(adx,"lua","ToGame",string.pack(">I2>I2c"..string.len(msg), CMD.Main_hall_module,CMD.Sub_ClientToHall_CreateAgentTableReq2, msg))

end

--游戏服务器返回二次创建房间结果
function HALL.CreateAgentTableResp2( msg )
    -- 需要转给代理人
    local agentid,tableid,flag = string.unpack("<I4I4i4", msg, 5)
    skynet.error("收到游戏服传来的2次创建结果 agentid="..agentid.." tableid="..tableid.." flag="..flag)

    HALL.sendMsgByPlay(agentid,CMD.Main_hall_module,CMD.Sub_CreateAgentTableResp2,string.pack("<i4c128",flag,'游戏房间创建结果'))
end

--代理获取房间信息
function HALL.AgentGetRoomList( conf )
    -- 从DB中获取有关数据
    local s1, res = db.call("call  pr_AgentGetTableList2("..conf.playid..",@ReturnVal)","select @ReturnVal")

    local result = res[1]['@ReturnVal']

    skynet.error("[HALL.AgentGetRoomList] playid = "..conf.playid.." result = "..result)

    if result<0 then  -- 不是代理
        local re = {mcmd = CMD.Main_hall_module,scmd = CMD.Sub_AgentRoomList, msg = string.pack("<I4I4",0,0) }
        return re
    end

    local data_count = 0
    local bin_data = ""
    for k,i in pairs(s1[1]) do
        print("k="..k.." i="..i['tm'].." mode:"..i['nMode'])
        local roominfo = string.sub(i['RoomInfo'],1,128)
        data_count = data_count + 1
        bin_data = bin_data..string.pack("<I4I4I4I4c128",i['nTableID'],i['extendCode'],i['nMode'],tonumber(i['tm']),roominfo)
    end

    skynet.error("[HALL.AgentGetRoomList] data_count = "..data_count)

    local re = {mcmd = CMD.Main_hall_module,scmd = CMD.Sub_AgentRoomList, msg = string.pack("<I4<I4c"..string.len(bin_data),1,data_count,  bin_data )}
    return re

end

--代理解散桌子
function HALL.AgentDismissTable( conf )
    -- 需要找到对应服务器并发送请求
    local pid = conf.playid
    local msg = conf.msg
    local tableid = string.unpack("<I4",conf.msg,1)
    skynet.error("代理解散桌子请求 id="..pid.." tableid="..tableid)
    
    local tid = tonumber(string.sub(tostring(tableid),1,2))

    if GameServerShareObj.tableobj[tid]~= nil then
        local gs_addr = GameServerShareObj.tableobj[tid]
        skynet.error("通知游戏服务器  addr= "..gs_addr)
        skynet.send(gs_addr,"lua","ToGame",string.pack(">I2>I2<I4<I4", CMD.Main_hall_module,CMD.Sub_ClientToHall_AgentDismissTable,pid,tableid))
    end

    -- 测试  应该是返回后才发送
    -- HALL.AgentGetRoomList({playid = pid})

    --测试数据，直接发送给客户端
    -- local re = {mcmd = CMD.Main_hall_module,scmd = CMD.Sub_AgentDismissTableResp, msg = string.pack("<I4<I4c128",tableid,1,"解散桌子完成" )}
    -- return re

end

--用户请求更新钻石
-- function HALL.ClientUpdateDiamondReq( conf )
--     -- 直接去数据库查询将结果发送给对应playerid
--     local pid = conf.playid

--     local res = db:query("call  Pr_UserGetDiamond("..conf.playid..",@intDiamond,@ReturnVal)")
--     local r1  = db:query("select @ReturnVal,@intDiamond")

--     local result   = r1[1]['@ReturnVal']
--     local nDiamond = r1[1]['@intDiamond']

--     skynet.error("[HALL.ClientUpdateDiamondReq] playid="..conf.playid.." re="..result.." diamond="..nDiamond)

--     local re = {mcmd = CMD.Main_hall_module,scmd = CMD.Sub_ClientUpdateDiamondResp, msg = string.pack("<I4<I4",pid,nDiamond)}
--     return re
-- end

--游戏服通知桌子解散
function HALL.NotifyTableDismiss( msg )
    
    local agentid ,tableid = string.unpack("<I4<I4",msg,5)
    skynet.error("[HALL.NotifyTableDismiss] agentid="..agentid.." tableid="..tableid)

    -- 通知对应代理人 更新钻石
    HALL.sendMsgByPlay(agentid,CMD.Main_hall_module,CMD.Sub_NotifyClientUpdateDiamond,"")

end

-- 游戏服返回解散结果
function HALL.AgentDismissTblResp( msg )
    local agentid, tblid,result = string.unpack("<I4I4i4",msg,5)
    skynet.error("[HALL.AgentDismissTblResp] agentid="..agentid.." table="..tblid.." result="..result)

    local szmsg
    if result == 1 then
        szmsg = "解散桌子完成"
    else
        szmsg = "解散桌子失败,可能已经开始游戏"
    end
    HALL.sendMsgByPlay(agentid,CMD.Main_hall_module,CMD.Sub_AgentDismissTableResp,string.pack("<I4<I4c128",tblid,result,szmsg ))
end

function HALL.UserActGroup(playid,msg)
    local nAct,nGroupId,szRemarks = string.unpack("iic128",msg,1)

    local sql = ""

    skynet.error("nAct = ",nAct)
    if nAct == 0 then
        sql = sql.."call Pr_SpcTableUserQuit("
    else
        sql = sql.."call Pr_SpcTableUserJoin("
    end

    sql = sql..playid..','..nGroupId..',\"'..szRemarks..'\",@intResult,@szReturnMsg,@returnVal)'

    local res1,res2 = db.call(sql,"select @intResult,@szReturnMsg,@returnVal")

    if res2 and res2[1] then
        local result,szReturnMsg = res2[1]['@intResult'],res2[1]['@szReturnMsg']
        if tonumber(result) == 0 then
            HALL.SendCenterHintMsg(playid,szReturnMsg)
            return
        end

        if tonumber(nAct)==1 then
            HALL.SendCenterHintMsg(playid,"申请已提交待审核!")
            return
        end

        local res = string.pack("ii",result,nGroupId)
        HALL.sendMsgByPlay(math.floor(nPlayerId),CMD.Main_hall_module,CMD.Sub_HallToClient_UserActGroup,res)
        return
    end
    skynet.error("加群退群数据库操作错误")
end

function HALL.GetUserGroupID(playid)
    local sql = "call Pr_SpcTableGetUserGroupNo("..playid..")"
    local res1 = db.call(sql)
    local msg = string.pack("I2",#res1[1])
    for index,row in pairs(res1[1]) do
       msg = msg..string.pack("i",tonumber(row['GroupNo']))
    end
    HALL.sendMsgByPlay(math.floor(playid),CMD.Main_hall_module,CMD.Sub_HallToClient_GetUserGroupID,msg)
end

function HALL.GetUserApplyGroupList(playid)
    local  sql = "call Pr_Loadfriendslog("..playid..")"
    local rows = db.call(sql)
    local msg = string.pack("i",#rows[1])
    if rows and rows[1] then
        for index,row in pairs(rows[1]) do
            msg = msg..string.pack("iic32",tonumber(row['GroupNo']),tonumber(row['Status']),tostring(row['ActTime']))
        end
    end
    HALL.sendMsgByPlay(math.floor(playid),CMD.Main_hall_module,CMD.Sub_HallToClient_GetUserApplyGroupList,msg)
end

function HALL.QueryUserGroupID(playid,msg)
    local userid = string.unpack("i",msg,1)
    local  sql = "call Pr_SpcTableGetUserGroupNo("..userid..")"
    local rows = db.call(sql)
    local msg = string.pack("i",userid)
    msg = msg..string.pack("i",#rows[1])
    if rows and rows[1] then
        for index,row in pairs(rows[1]) do
            msg = msg..string.pack("i",tonumber(row['GroupNo']))
        end
    end
    HALL.sendMsgByPlay(math.floor(playid),CMD.Main_hall_module,CMD.Sub_HallToClient_QueryUserGroupID,msg)
end

function response.request_hall(conf)--{cmd,playid,msg}
    skynet.error("[hallser] 收到子码 = "..conf.cmd)

    -- if conf.cmd == CMD.Sub_RegToHall then
    --     return HALL.GameServerReg(conf.msg,conf.addr)
    -- elseif conf.cmd == CMD.Sub_UnRegToHall then
    --     return HALL.GameServerUnReg(conf.msg,conf.addr)
    -- end

    -- 客户端请求创建代理房间
    if conf.cmd == CMD.Sub_ClientToHall_CreateAgentTableReq then
        return HALL.CreateAgentTableReq(conf.msg)
    elseif conf.cmd == CMD.Sub_ClientToHall_CreateAgentTableReq2 then
        return HALL.CreateAgentTableReq2(conf.msg)
    elseif conf.cmd == CMD.Sub_ClientToHall_AgentGetRoomList then
        return HALL.AgentGetRoomList(conf)
    elseif conf.cmd == CMD.Sub_ClientToHall_AgentDismissTable then
        return HALL.AgentDismissTable(conf)
    -- elseif conf.cmd == CMD.Sub_ClientToHall_ClientUpdateDiamondReq then
    --     return HALL.ClientUpdateDiamondReq(conf)
    elseif conf.cmd == CMD.Sub_NotifyTableDismiss then --(游戏服务器通知中心服)
        return HALL.NotifyTableDismiss(conf.msg)
    elseif conf.cmd == CMD.Sub_CreateAgentTableResp2 then --(游戏服返回创建桌子结果)
        return HALL.CreateAgentTableResp2(conf.msg)
    elseif conf.cmd == CMD.Sub_AgentDismissTableResp then --(游戏服返回解散桌子结果)
        return HALL.AgentDismissTblResp(conf.msg)
    elseif conf.cmd == CMD.Sub_ClientToHall_UserActGroup then --加入退出亲友群
        return HALL.UserActGroup(conf.playid,conf.msg)
    elseif conf.cmd == CMD.Sub_ClientToHall_GetUserGroupID then --获取亲友群ID
        return HALL.GetUserGroupID(conf.playid)
    elseif conf.cmd == CMD.Sub_ClientToHall_GetUserApplyGroupList then --获取亲友群申请记录
        return HALL.GetUserApplyGroupList(conf.playid)
    elseif conf.cmd == CMD.Sub_ClientToHall_QueryUserGroupID then --查询某人的亲友群信息
        return HALL.QueryUserGroupID(conf.playid,conf.msg)
    end

	return nil
end

function HALL.SendCenterHintMsg(playid,msg)
    HALL.sendMsgByPlay(playid,MAIN.Main_ClientAndGameSvr_UserModle, MAIN.Sub_GameSvrToClient_UserModle_HingMsg,msg)
end

--可以按用户ID来发送消息
function HALL.sendMsgByPlay(playid,mcmd,scmd,msg)
    
    local ok = pcall(HALL.sendMsg,playid,mcmd,scmd,msg)
    if not ok  then 
        skynet.error("[hallser] sendMsgByPlay error ")
    end
    
end

function HALL.sendMsg(...)
    
    if centerserver then 
        cluster.send("master", centerserver,"send_GateMail",...)
    else
        centerserver = cluster.query("master", "centerser")
        cluster.send("master", centerserver,"send_GateMail",...)        
    end

end

--用于测试用
function HALL.testsendMsgByPlay()
    skynet.error("start testsendMsgByPlay 22 ")
    skynet.fork(function()
        while true do
            skynet.error("start testsendMsgByPlay ")

            HALL.sendMsgByPlay(67978,22,22,"hello1")
            HALL.sendMsgByPlay(67978,22,22,"hello2")
            HALL.sendMsgByPlay(67978,22,22,"hello3")
            HALL.sendMsgByPlay(67978,22,22,"hello4")
            HALL.sendMsgByPlay(67978,22,22,"hello5")
            HALL.sendMsgByPlay(67978,22,22,"hello6")

            skynet.sleep(300)
        end
    end)
end


function HALL.start(...)
  
    GameServerShareObj  = sharedata.query "GameServerShareObj"

    --centerserver = cluster.snax("center", "centerser")
    
end


function init( ... )
	skynet.error("hallser server start:")
	snax.enablecluster()
    HALL.start(...)
end

function exit(...)
	skynet.error ("hallser server exit:", ...)
end
